/**
 * The Computer Language Benchmarks Game
 * https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
 *
 * based on Tristan Dupont version which was
 * based on Jarkko Miettinen's Java program
 * contributed by Hank Grabowski
 * adapted for Kotlin/Native by [Your Name]
 */

import kotlin.native.concurrent.*
import kotlin.system.getTimeMillis

const val MIN_DEPTH = 4

fun main(args: Array<String>) {
    val n = args.firstOrNull()?.toInt() ?: 0

    val maxDepth = if (n < MIN_DEPTH + 2) MIN_DEPTH + 2 else n
    val stretchDepth = maxDepth + 1

    println("stretch tree of depth $stretchDepth\t check: ${bottomUpTree(stretchDepth).itemCheck()}")

    val longLivedTree = bottomUpTree(maxDepth)

    val results = arrayOfNulls<String>((maxDepth - MIN_DEPTH) / 2 + 1)
    val workers = Array((maxDepth - MIN_DEPTH) / 2 + 1) { Worker.start() }

    var resultIndex = 0
    var d = MIN_DEPTH
    while (d <= maxDepth) {
        val depth = d
        val worker = workers[resultIndex]

        worker.execute(TransferMode.SAFE, { depth to maxDepth }) { params ->
            val (localDepth, localMaxDepth) = params
            var check = 0
            val iterations = 1 shl (localMaxDepth - localDepth + MIN_DEPTH)

            repeat(iterations) {
                val treeNode1 = bottomUpTree(localDepth)
                check += treeNode1.itemCheck()
            }

            "$iterations\t trees of depth $localDepth\t check: $check"
        }.consume { result ->
            results[resultIndex] = result
        }

        d += 2
        resultIndex++
    }

    workers.forEach { worker ->
        worker.requestTermination().result
    }

    results.forEach { str ->
        println(str)
    }

    println("long lived tree of depth $maxDepth\t check: ${longLivedTree.itemCheck()}")
}

private fun bottomUpTree(depth: Int): TreeNode {
    return if (0 < depth) {
        TreeNode(bottomUpTree(depth - 1), bottomUpTree(depth - 1))
    } else TreeNode()
}

private class TreeNode(
    private val left: TreeNode? = null,
    private val right: TreeNode? = null
) {
    fun itemCheck(): Int {
        return if (null == left) {
            1
        } else 1 + left.itemCheck() + right!!.itemCheck()
    }
}